package UI;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import java.io.File;

import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;

import util.Logger;
import util.SerializationHelper;

import client.ClientDirectory;
import client.MessageHandler;
import dataContracts.InstallSettings;
import dataContracts.SharedFile;

public class UI implements MouseListener, ActionListener {

	private ClientDirectory cd;	
	MessageHandler messageHandler;
	UIinstaller configurator;
	SerializationHelper<InstallSettings> sh;
	InstallSettings is;
	
	//CONSTANTS
	private static final int WIDTH = 900;
	private static final int HEIGHT = 650;
	private static final Color highlightCOLOR = new Color(229,230,230);
	private static final String APPNAME = "LANyard";
	
	//BUILDER OBJECT
	public static UIbuilder builder;
	
	//RUN METHOD
	//sets look and feel
	public static void run() {
		
		try {
		 for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
		        if ("Nimbus".equals(info.getName())) {
		            UIManager.setLookAndFeel(info.getClassName());
		            break;
		        }
		    }
		} catch (Exception e) {
			try {
				UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			} catch (ClassNotFoundException e1) {
				e1.printStackTrace();
			} catch (InstantiationException e1) {
				e1.printStackTrace();
			} catch (IllegalAccessException e1) {
				e1.printStackTrace();
			} catch (UnsupportedLookAndFeelException e1) {
				e1.printStackTrace();
			}
		}
	
	}
	
	//CONSTRUCTOR --------------------------------
	
    public UI(MessageHandler msgHandler, ClientDirectory clientDirectory) {
    	//initialize messenger
    	messageHandler = msgHandler;
    	messageHandler.ui = this;
    	//at this point we have an object to which we will delegate all server communication
    	//to add a new method call, just add an actionListener to the MessageHandler class
    	//and that actionListener has access to both this UI and the ClientProgram class which does the socket I/O
    	
    	//set client directory
    	cd = clientDirectory;
    	
    	//instantiate the user interface builder
    	builder = new UIbuilder(cd, this, msgHandler);
    	
    	//BUILD THE USER INTERFACE ------
    	
    	JFrame frame = builder.makeFrame(WIDTH, HEIGHT, APPNAME, "frame", new ImageIcon("images/lyLogo.png"));
    	
        //TOOLBAR
    	JToolBar tb = builder.makeToolBar(frame.getWidth());
        frame.getContentPane().add(tb, builder.gbcHandler("tb"));
        //SPLITPANE
        JSplitPane sp = builder.makeSplitPane(frame.getWidth());
        frame.getContentPane().add(sp, builder.gbcHandler("sp"));
        
        frame.setVisible(true);   
        
    }
    
    //CORE PROGRAM FUNCTIONALITY -----------------------------
    
    private void addFile() throws IOException{
        JFileChooser c = new JFileChooser();
        int returnVal = c.showOpenDialog(builder.lanyard);
        
        if(returnVal == JFileChooser.APPROVE_OPTION) {
        	
        	String orig = c.getSelectedFile().getAbsolutePath();
        	String dest = cd.getFilePath() + File.separator + c.getSelectedFile().getName();
        	
        	InputStream in = new FileInputStream(orig);
        	OutputStream out = new FileOutputStream(dest);

        	byte[] buf = new byte[1024];
        	
        	int len;
        	
        	while ((len = in.read(buf)) > 0) {
        			out.write(buf, 0, len);
        	}
        	
        	in.close();
        	out.close();
	
        	cd.refresh();
        	builder.redrawLeftPane();
        		
        	messageHandler.addFile(c.getSelectedFile().getName());
        }
    }
    
    private void removeFile() throws IOException{
    	SharedFile toRemove = cd.findFile(builder.active.getName());
    	
    	messageHandler.deleteFile(builder.active.getName());
    	
    	cd.removeFile(toRemove);
    	
    	cd.refresh();
    	builder.redrawLeftPane();
    }
    
  //HELPER METHODS ----------------------------------------------
    
    private void setupMetaData(){
    	
    	if(builder.active != null){
    		SharedFile sf = cd.findFile(builder.active.getName());
    		
    		sf.setProject(builder.project.getText());
    		sf.setTags(builder.tags.getText());
    		sf.setComments(builder.comments.getText());
    		
    		messageHandler.saveAttributes(sf);
    		
    	} else {
    		//NOPE, select a file, jerk
    	}
    	
    }
    
    public void servLog(String msg){
    	builder.serverLogTextBox.setText(builder.serverLogTextBox.getText() + msg + "\n");
    }

    //EVENT HANDLERS ----------------------------
    
	@Override
	public void mouseClicked(MouseEvent e) {
		
		//handle the null case
		if(builder.active == null){	
			builder.active = e.getComponent();						//store the value
			builder.active.setBackground(new Color(200,230,230));	//highlight the panel
		
		//handle nominal case	
		} else if(!builder.active.equals(e.getComponent())){
			builder.active.setBackground(highlightCOLOR);			//reset color on previous selection
			builder.active = e.getComponent();						//replace "active" component
			builder.active.setBackground(new Color(200,230,230));	//highlight the panel
		}
		
		//update file metadata information
		builder.updateMetaData();
		
	}

	@Override
	public void mouseEntered(MouseEvent e) {}

	@Override
	public void mouseExited(MouseEvent e) {}

	@Override
	public void mousePressed(MouseEvent e) {}

	@Override
	public void mouseReleased(MouseEvent e) {}

	@Override
	public void actionPerformed(ActionEvent e) {
		
		String command = e.getActionCommand();
		
		//commit additions to metadata
		if(command.equals("Commit")){
			setupMetaData();
		
		//add a file to the collection
		} else if (command.equals("Add")){
			try {
				addFile();
			} catch (IOException e1) {
				//THROW FILE NOT FOUND BOX
			}
		
		//remove a file from the collection	
		} else if (command.equals("Del")){
			try {
				removeFile();
			} catch (IOException e1) {
				//THROW FILE NOT FOUND BOX
			}
		
		//exit the program
		} else if (command.equals("Exit")){
			//do some exit procedure
		
		//refresh the file list
		} else if (command.equals("Refresh")){
			builder.redrawLeftPane();
		
		//configure the application
		} else if (command.equals("Config")){
			configurator.run(cd.config);
		
		//synchronize application
		} else if (command.equals("Sync")){
			messageHandler.RequestSynch();
		}
	
	}
    
}